Support tracking HTTP request overall progress and cancellation - #669
Conversation
| /// parameter, which must satisify following requirements: | ||
| /// - `totalUnitCount` must not be zero. | ||
| /// - `completedUnitCount` must be zero. | ||
| /// - It's used exclusivity for tracking the HTTP request overal progress: No children in its progress tree. |
There was a problem hiding this comment.
| /// - It's used exclusivity for tracking the HTTP request overal progress: No children in its progress tree. | |
| /// - It's used exclusively for tracking the HTTP request overall progress: No children in its progress tree. |
| /// You can track the HTTP request's overall progress by passing a `Progress` instance to the `fulfillingProgress` | ||
| /// parameter, which must satisify following requirements: | ||
| /// - `totalUnitCount` must not be zero. | ||
| /// - `completedUnitCount` must be zero. | ||
| /// - It's used exclusivity for tracking the HTTP request overal progress: No children in its progress tree. | ||
| /// - `cancellationHandler` must be nil. You can call `fulfillingProgress.cancel()` to cancel the ongoing HTTP request. |
There was a problem hiding this comment.
What do you think about encoding these constraints in either a dedicated type that wraps Progress or a subclass/pre-configured instance?
Type wrapping Progress
More coding and less flexibility for advanced users, but no chance of misuse since we'd be controlling everything from here
Subclass / Preconfigured instance
Could be misuses, but by letting the method accept a Progress type, we'd give power users more flexibility
There was a problem hiding this comment.
Update: I saw the assert below. They do a good job at ensuring runtime safety. Still, from a "how many things does a user need to know?" perspective, I think leveraging the type system somehow would be beneficial.
|
|
||
| let (body, response) = result | ||
| if let parentProgress, parentProgress.totalUnitCount > parentProgress.completedUnitCount { | ||
| let pending = parentProgress.totalUnitCount - parentProgress.completedUnitCount |
There was a problem hiding this comment.
Do we need this math given the assert above for completedUnitCount == 0?
There was a problem hiding this comment.
No, I don't think it's needed. But, in my head, the code expresses the idea more explicitly: letting the task.progress fill parentProgress without overflowing.
Description
Note
This PR is built on top of #668
There are many existing APIs that returns a
Progressinstance, which can be used to track progress and some can be used to perform cancellation. This PR implements these features in the new URLSession helper.The existing APIs return a
Progressas function return value. We can't do the same, because the new helper is anasyncfunction: theProgresswill be no use if it's used as a return value. I used a parent progress instance instead. The caller now needs to pass in a validProgressinstance that's created exclusively for the HTTP request, and it'll be completed upon the completion of the HTTP request.Another approach I tried is using a
inout Progressargument, so that we don't need to create a duplicated progress instance. I envisioned it can be used as below, but ended up getting a compiler error.Testing Details
See the added unit tests.
CHANGELOG.mdif necessary.